package com.wiscamp.ninechapters.panels.domain.services;

import com.wiscamp.ninechapters.panels.domain.repositories.PanelsErrorCodes;
import com.wiscamp.ninechapters.panels.domain.entities.Dictionary;
import com.wiscamp.ninechapters.panels.domain.repositories.DictionaryRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.DomainService;
import cube.ddd.exception.ExceptionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class DictionaryService implements DomainService {
    private final DictionaryRepository dictionaryRepository;

    private final String cacheName = "dictionaries";

    public DictionaryService(DictionaryRepository dictionaryRepository) {
        this.dictionaryRepository = dictionaryRepository;
    }

    @HandleServiceException
    @Cacheable(value = cacheName, key = "#dictionaryId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Dictionary getDictionary(long dictionaryId) {
        var dictionary = dictionaryRepository.getDictionary(dictionaryId);
        if (Objects.isNull(dictionary)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.DICTIONARY_NOT_FOUND, dictionaryId);
        }
        return dictionary;
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#dictionary.dictionaryId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Dictionary createDictionary(Dictionary dictionary, long operatorId) {
        var existedDictionary = dictionaryRepository.getDictionaryByCode(dictionary.getApplicationId(), dictionary.getDictionaryCode());
        if (Objects.nonNull(existedDictionary)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.DICTIONARY_CODE_EXISTED, dictionary);
        }
        dictionary.createBy(operatorId);
        return dictionaryRepository.saveDictionary(dictionary);
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#dictionary.dictionaryId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Dictionary updateDictionary(Dictionary dictionary, long operatorId) {
        var existedDictionary = getDictionary(dictionary.getDictionaryId());

        existedDictionary = dictionaryRepository.getDictionaryByCode(dictionary.getApplicationId(), dictionary.getDictionaryCode());
        if (Objects.nonNull(existedDictionary) && existedDictionary.getDictionaryId() != dictionary.getDictionaryId()) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.DICTIONARY_CODE_EXISTED, dictionary);
        }
        dictionary.updateBy(operatorId);
        return dictionaryRepository.saveDictionary(dictionary);
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#dictionaryId")
    public boolean enableDictionary(long dictionaryId, long operatorId) {
        var dictionary = getDictionary(dictionaryId);
        if (Objects.isNull(dictionary)) return false;
        // 记录操作日志
        dictionary.enable();
        dictionary.updateBy(operatorId);
        dictionaryRepository.saveDictionary(dictionary);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#dictionaryId")
    public boolean disableDictionary(long dictionaryId, long operatorId) {
        var dictionary = getDictionary(dictionaryId);
        if (Objects.isNull(dictionary)) return false;
        // 记录操作日志
        dictionary.disable();
        dictionary.updateBy(operatorId);
        dictionaryRepository.saveDictionary(dictionary);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#dictionaryId")
    public boolean deleteDictionary(long dictionaryId, long operatorId) {
        var dictionary = getDictionary(dictionaryId);
        if (Objects.isNull(dictionary)) return false;
        // 记录操作日志
        dictionary.delete();
        dictionary.updateBy(operatorId);
        dictionaryRepository.saveDictionary(dictionary);
        return true;
    }
}
